package gee

import (
	"log"
	"net/http"
	"path"
	"strings"
)

type RouterGroup struct {
	prefix      string
	middlewares []HandleFunc
	parent      *RouterGroup
	engine      *Engine
}

//中间件置入
func (routerGroup *RouterGroup) Use(handle HandleFunc) {
	routerGroup.middlewares = append(routerGroup.middlewares, handle)
}

func (routerGroup *RouterGroup) Group(str1 string) *RouterGroup {
	var build strings.Builder
	build.Grow(len(str1) + len(routerGroup.prefix) + 2)
	build.WriteString(str1)
	build.WriteString(routerGroup.prefix)
	result := &RouterGroup{
		prefix:      build.String(),
		middlewares: make([]HandleFunc, 0),
		parent:      routerGroup,
		engine:      routerGroup.engine,
	}
	routerGroup.engine.groups = append(routerGroup.engine.groups, result)
	return result
}

func (routerGroup *RouterGroup) addRoute(myMethod string, pattern string, handle HandleFunc) {
	var build strings.Builder
	build.Grow(len(routerGroup.prefix) + len(pattern) + 2)
	build.WriteString(routerGroup.prefix)
	build.WriteString(pattern)
	way := build.String()
	log.Printf("Route %4s - %s", myMethod, way)
	routerGroup.engine.router.addRoute(myMethod, way, handle)
}

func (routerGroup *RouterGroup) GET(pattern string, handle HandleFunc) {
	routerGroup.addRoute("GET", pattern, handle)
}

func (routerGroup *RouterGroup) POST(pattern string, handle HandleFunc) {
	routerGroup.addRoute("POST", pattern, handle)
}

func (r *RouterGroup) createStaticHandler(relaterSo string, fs http.FileSystem) HandleFunc {
	// var builder strings.Builder
	// builder.Grow(len(r.prefix) + len(relaterSo) + 2)
	// builder.WriteString(r.prefix)
	// builder.WriteString(relaterSo)//不用这个，是因为没有加斜杆
	absolutePath := path.Join(r.prefix, relaterSo)
	//在处理器中添加一项处理，去除url中的前缀absolutePath，然后处理器再把url与服务器的本地文件系统映射，
	fileServer := http.StripPrefix(absolutePath, http.FileServer(fs))
	return func(context *Context) { //闭包，跟C++不一样，会自动捕获前面的变量
		file := context.Param("filePath")
		//fs本身就是映射的目录，所以不需要file拼接前面的路径
		if _, err := fs.Open(file); err != nil {
			context.W.WriteHeader(http.StatusNotFound)
			context.StatusCode = http.StatusNotFound
			context.W.Write([]byte("404 not found.file is not exist"))
			return
		}
		fileServer.ServeHTTP(context.W, context.Req)
	}
}

//映射文件路径，静态资源服务器
func (r *RouterGroup) StaticFileSource(relaterPath string, filePtah string) {
	result := r.createStaticHandler(relaterPath, http.Dir(filePtah))
	// var builder strings.Builder
	// builder.Grow(len(r.prefix) + len(relaterPath) + 2)
	// builder.WriteString(r.prefix)
	// builder.WriteString(relaterPath)
	//不需要加前缀
	r.GET(path.Join(relaterPath, "/*filePath"), result)
}
